﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Threading;
using System.Net;

using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace DIMP_Libraries
{
    public class Serveur
    {
        protected TcpListener _tl;
        public List<ClientServeur> _clients;
        protected Thread _connexionThread;
        protected Thread _checkThread;
        public Boolean _running;
        public event EventHandler<MessageEventArg> onMessageReceived;
        public event EventHandler onClientConnected;

        public Serveur(Int32 port)
        {
            _clients = new List<ClientServeur>();
            _tl = new TcpListener(new IPEndPoint(IPAddress.Any, port));
            _running = true;

            _connexionThread = new Thread(ConnexionListener);
            _connexionThread.Start();

            _checkThread = new Thread(CheckListener);
            _checkThread.Start();

        }


        /*
         * Thread d'attente des connexions
         */
        private void ConnexionListener()
        {
            _tl.Start();
            while (_running)
            {
                while (_tl.Pending() == false) { System.Threading.Thread.Sleep(10); }//this is the part with the lag
                TcpClient cl = _tl.AcceptTcpClient();
                Thread proct = new Thread(new ParameterizedThreadStart(TraitementClient));
                proct.Start(cl);
                break;
            }
        }


        /*
         * Thread de vérification de la connexion des clients
         */
        private void CheckListener()
        {
            while (true)
            {
                for (int i = _clients.Count-1; i >= 0; i--)
                {
                    if (!checkDisconnected(_clients[i].getTcpClient()))
                    {
                        _clients.Remove(_clients[i]);
                    }
                }
                Thread.Sleep(3000);
            }
        }

        /*
         * Retourne true si encore connecté
         */
        private Boolean checkDisconnected(TcpClient client)
        {

            try
            {
                return !(client.Client.Available == 0 && client.Client.Poll(1, SelectMode.SelectRead));
            }
            catch (SocketException) { return false; }


        }

        /*
         * Action quand un client est connecté
         */
        private void TraitementClient(object client)
        {
            ClientServeur clientSrv = new ClientServeur((TcpClient)client);
            clientSrv.onMessageReceived += new EventHandler<MessageEventArg>(clientSrv_onMessageReceived);
            _clients.Add(clientSrv);
            onClientConnected(this, EventArgs.Empty);
        }


        /*
         * Quand un client a envoyé un message
         */
        public virtual void  clientSrv_onMessageReceived(object sender, MessageEventArg e)
        {
        }
    }
}
